/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			userfunc.h
  \date			Dec 2011
  \author		TNick

  \brief		Contains the definition for UserFunc class


*//*

 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __USERFUNC_INC__
#define __USERFUNC_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<QVector>

#ifdef	USE_USERMSG
#include	<UMSG.h>
#endif

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

namespace	PgScr	{

class	Module;
class	WorkUnit;
class	UserVar;
class	UserFunc;
class	VarStore;
struct	Session;
class	DefVar;


/// class representing a function that is interactable by user
class UserFunc				{

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

#ifdef	PGSCRIPT_TESTS
	friend void		Func_Tests	( int&, int& );
#endif



public:

	/// various information packed together
	enum		Flags		{
		FL_NONE = 0,				/**< simply tell that there's no flag set */

		FL_RETURN = 1 << 0,			/**< the function returns a value */
		FL_VARARG = 1 << 1,			/**< accept variable number of arguments */
		FL_PREDEF = 1 << 2,			/**< the function is a predefined one */

		FL_PERMANENET = 1 << 3,		/**< the function is to be preserved between sessions */

		FL_MAX						/**< for validation */
	};


	/// the definition for function used as callback
	/**
	  *	@return true to allow the change, false to reject it
	  */
	typedef	OUTCOME	(*kbEvaluate)	(
			VarStore &				the_res,	/**< the result of function evaluation */
			QVector<VarStore>		argum,		/**< the list of tokens */
			unsigned				arg_c		/**< number of arguments */
			);


	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

private:


	/// the string representing the name of this function
	QString			name_;


	/// various informatinos packed here
	Flags			flg_;


	/// number of fixed arguments
	int				arg_cnt_;


	/// the callback function
	kbEvaluate		kb_;


	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

private:

	/**
	*	@brief	used by constructors to perform common initialisation
	*/
	void		construct		( Module * mdl );



public:


	/**
	*	@brief	 Constructor; creates unnamed function in default session
	*/
	UserFunc		( void );


	/**
	*	@brief	 Constructor; named function in specified module
	*
	*	@param	f_name	name to assign to function
	*	@param	mdl		module where to create; if NULL is created in default
	*	session, default module
	*/
	UserFunc		(
			QString				f_name,
			Module *			mdl = NULL
			);

	/**
	*	@brief	 Constructor; named function in specified session, default module
	*
	*	@param	f_name	name to assign to function
	*	@param	trg_ss	the function is created in default module in this Session
	*	if NULL is created in default Session, default module
	*/
	UserFunc		(
			QString				f_name,
			Session *			trg_ss
			);


	/**
	*	@brief	 Constructor; named function in specified module
	*
	*	@param	f_name		name to assign to function
	*	@param	flgs		attributes that will be directly copied to function
	*	@param	mdl			module where to create; if NULL is created in default
	*	session, default module
	*/
	UserFunc		(
			QString				f_name,
			Flags				flgs,
			Module *			mdl = NULL
			);

	/**
	*	@brief	 Constructor; named function in specified session, default module
	*
	*	@param	f_name		name to assign to function
	*	@param	flgs		attributes that will be directly copied to function
	*	@param	trg_ss		the function is created in default module in this Session
	*	if NULL is created in default Session, default module
	*/
	UserFunc		(
			Session *			trg_ss,
			QString				f_name,
			Flags				flgs
			);


	/// destructor;
	virtual				~UserFunc		( void );





	/** @name Basic information
	 *	Basic information reported by a function are it's name and it's type
	 *	(identifying the class that implements UserVar). The name is managed
	 *	(stored, reported via name() and changed via setName() ) by this class and
	 *	the type() must be reported as a string by the implementation.
	 */
	//@{

	/// report the name of this function
	inline QString		name					( void ) const
	{ return name_; }


	/// change the name of the function
	inline void			setName					( QString s_new_name )
	{ name_ = s_new_name; }


	/// tell if the function returns a value
	inline bool			hasReturn				( void ) const
	{ return (flg_ & FL_RETURN) != 0; }


	/// the number of arguments for this function
	inline int			argCount				( void ) const
	{ return arg_cnt_; }


	/// tell if the function returns a value
	inline bool			hasVarArg				( void ) const
	{ return (flg_ & FL_RETURN) != 0; }


	/// tell if the function is permanently stored or is a session function
	inline bool			isPermanent				( void ) const
	{ if ( isPredef() ) return true; return ( ( flg_ & FL_PERMANENET) != 0 ); }


	/// request the application to store the function
	inline void			makePermanent			( void )
	{ setFlag( FL_PERMANENET ); }


	/// request the application not to store the function
	inline void			makeVolatile			( void )
	{ if ( ! isPredef() ) resetFlag( FL_PERMANENET ); }


	/// tell if the function is a build-in one or is a user-defined function
	inline bool			isPredef				( void ) const
	{ return ( ( flg_ & FL_PREDEF) != 0 ); }

	//@}


private:

	inline void		setFlag				( int new_flg )
	{ flg_ = static_cast<Flags> (flg_ | new_flg ); }

	inline void		resetFlag			( int new_flg )
	{ flg_ = static_cast<Flags> (flg_ & (~new_flg) ); }


	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class UserFunc	*/

/*  CLASS    =============================================================== */
//
//
//
//

void				Func_Tests					(
		int & performed,
		int & succeded
		);

}	//	namespace	PgScr

#endif // __USERFUNC_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
